package org.dslmagic.interpreter;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

import org.dslmagic.data.Group;
import org.dslmagic.dsl.Dsl;



public class StandardDslInterpreter extends BaseDslInterpreter {

	public Object get(Dsl dsl) {
		Object target = dsl.obj(0, this);
		String key = dsl.str(1, this);
		try {
			String prop = key.substring(0, 1).toUpperCase() + key.substring(1);
			Method method = target.getClass().getMethod("get" + prop);
			Object value = method.invoke(target);
			return value;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public Object call(Dsl dsl) {
		String methodName = dsl.str(0, this);
		Object[] args = dsl.group(1, this).toArray();
		return Dsl.create(methodName, args).visit(this);
	}

	public Object println(Dsl dsl) {
		String value = dsl.str(0, this);
		System.out.println(value);
		return value;
	}

	public Object test(Dsl dsl) {
		Object target = dsl.obj(0, this);
		set("$", target);
		Object value = dsl.obj(1, this);
		unset("$");
		return value;
	}

	public Object $(Dsl dsl) {
		return varobj("$");
	}

	public Object like(Dsl dsl) {
		return dsl.str(0, this).contains(dsl.str(1, this));
	}

	public Object eq(Dsl dsl) {
		return dsl.obj(0, this).equals(dsl.obj(1, this));
	}

	public Object gt(Dsl dsl) {
		return dsl.num(0, this) > dsl.num(1, this);
	}

	public Object gte(Dsl dsl) {
		return dsl.num(0, this) >= dsl.num(1, this);
	}

	public Object lt(Dsl dsl) {
		return dsl.num(0, this) < dsl.num(1, this);
	}

	public Object lte(Dsl dsl) {
		return dsl.num(0, this) <= dsl.num(1, this);
	}

	public Object compare(Dsl dsl) {
		Object[] args = vargroup("$args").toArray();

		set("$", args[0]);
		int measure1 = dsl.num(0, this);
		unset("$");

		set("$", args[1]);
		int measure2 = dsl.num(0, this);
		unset("$");

		return measure1 - measure2;
	}

	public Object and(Dsl dsl) {
		dsl.extract();
		Boolean[] values = dsl.bools(this);
		for (Boolean value : values) {
			if (!value) {
				return false;
			}
		}
		return true;
	}

	public Object or(Dsl dsl) {
		dsl.extract();
		Boolean[] values = dsl.bools(this);
		for (Boolean value : values) {
			if (value) {
				return true;
			}
		}
		return false;
	}

	public Object size(Dsl dsl) {
		Object obj = dsl.obj(0, this);
		if (obj instanceof String) {
			String str = (String) obj;
			return str.length();
		}
		if (obj instanceof Object[]) {
			Object[] array = (Object[]) obj;
			return array.length;
		}
		if (obj instanceof Collection<?>) {
			Collection<?> coll = (Collection<?>) obj;
			return coll.size();
		}
		return null;
	}

	public Object filter(Dsl dsl) {
		Group group = dsl.group(1, this);
		for (Iterator<?> iterator = group.iterator(); iterator.hasNext();) {
			Object item = iterator.next();
			set("$", item);
			if (!dsl.bool(0, this)) {
				iterator.remove();
			}
			unset("$");
		}
		return group.value();
	}

}
